package com.snow.java.base.junit;

import com.snow.java.base.entity.Student;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

/**
 * @类名称：
 * @类描述：
 * @author: bingHeng
 * @Date 2019.04.05
 * @Version: 1.0
*/
public class MyStream2 {

    /**
     * Stream API的中间操作
     *
     * 筛选与切片
     * filter： 接收Lambda，从流中排出某些元素
     * limit：截断流，使其元素不超过给定数量
     * skip(n): 跳过元素，返回一个扔掉了前n个元素的流，若流中元素不足n个，则返回一个空流，与limit(n)互补
     * distinct：筛选，通过流所产生的元素hashCode()和equals()去除重复元素
     *
     * stream的中间操作：
     *      多个中间操作可以连接起来形成一个流水线，除非流水线上触发终止操作，否则中间操作不会执行任何的处理，而在终止操作时一次性全部处理，称为“惰性求值”
     *
     * 映射☆：
     *      map：接收Lambda，将元素转换成其他形式或者提取信息，接收一个函数作为参数，该函数会被应用到每个元素上，并将其映射成一个新的元素。
     *      flatMap：接收一个函数作为参数，将流中的每个值都换成另一个流，然后把所有流连接成一个流
     *
     * 排序：
     *      sorted()：自然排序
     *      sorted(Comparator com):定制排序
     *
     */

    public static void main(String[] args) {


        List<Student> studentList = Arrays.asList(
                new Student(1, "张三", 2, 1, 85),
                new Student(2, "李四", 2, 2, 60),
                new Student(3, "王五", 2, 3, 100),
                new Student(4, "赵柳", 2, 4, 30),
                new Student(5, "大仙", 2, 5, 25),
                new Student(6, "小鬼", 2, 6, 74),
                new Student(1, "张三", 2, 1, 85),
                new Student(100, "张三", 2, 1, 85)
        );

        // filter

        // 过滤分数大于60的
        Stream<Student> studentStream = studentList.stream().filter((m) -> {

            System.out.println("这是stream API的中间操作");
            return m.getScore() > 60;

        });

        // 终止操作
        studentStream.forEach(System.out::println);

        System.out.println("===========================我是黄金分割线1===========================");
        // limit 在分数大于60分的学生中，仅仅打印出一个学生的成绩
        studentList.stream().filter((m) -> m.getScore() > 60).limit(1).forEach(System.out::println);

        System.out.println("===========================我是黄金分割线2===========================");
        // skip 在所有学生中，跳过前两个，仅仅打印后面的学生
        studentList.stream().skip(2).forEach(System.out::println);

        // distinct  对象中必须重写hashCode()和equals()
        System.out.println("===========================我是黄金分割线3===========================");
        studentList.stream().distinct().forEach(System.out::println);

        //映射 map
        System.out.println("===========================我是黄金分割线4===========================");
        List<String> list = Arrays.asList("hello world", "http", "lambda", "stream api");
        list.stream().map((m) -> m.toUpperCase()).forEach(System.out::println);
        studentList.stream().map(Student::getName).forEach(System.out::println);

        System.out.println("===========================我是黄金分割线5===========================");
        Stream<Stream<Character>> streamStream = list.stream().map(MyStream2::filterCharacter);
        streamStream.forEach((x) -> x.forEach(System.out::println));

        Stream<Character> characterStream = list.stream().flatMap(MyStream2::filterCharacter);
        characterStream.forEach(System.out::print);

        // 排序
        System.out.println("===========================我是黄金分割线6===========================");
        List<String> stringList = Arrays.asList("ccc", "bbb", "aaa");
        stringList.stream().sorted().forEach(System.out::println);

        //定制排序：按照分数排序，分数一样，按照id排
        studentList.stream().sorted((x1, x2) -> {
            if(x1.getScore() == x2.getScore()) {
                return x2.getId() - x1.getId();
            } else {
                return x1.getScore() - x2.getScore();
            }
        }).forEach(System.out::println);


    }

    public static Stream<Character> filterCharacter(String str) {
        List<Character> list = new ArrayList<>();
        for(Character c : str.toCharArray()) {
            list.add(c);
        }
        return list.stream();
    }
}
